
package com.graphite.client;

import com.graphite.model.GraphiteMetric;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.serialization.ObjectEncoder;
import io.netty.handler.codec.string.StringEncoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;


/**
 * @projectName: collect-service
 * @packageName: com.graphite.client
 * @className: com.graphite.client-> GraphiteClient
 * @createDate: 2021-05-31 17:17
 * @author: ZhangSheng
 * @version: 1.0
 * @description: GraphiteNettyClientTask 客户端访问graphite的线程包装类
 */
public class GraphiteNettyClientTask implements Callable<Boolean> {
    private static Logger logger = LoggerFactory.getLogger(GraphiteNettyClientTask.class);
    private String host;
    private int port;
    private List<GraphiteMetric> graphiteMetrics;

    public GraphiteNettyClientTask() {
    }

    public GraphiteNettyClientTask setHost(String host) {
        this.host = host;
        return this;
    }

    public GraphiteNettyClientTask setPort(int port) {
        this.port = port == 0 ? 2003 : port;
        return this;
    }

    public GraphiteNettyClientTask setGraphiteMetric(List<GraphiteMetric> graphiteMetrics) {
        this.graphiteMetrics = graphiteMetrics;
        return this;
    }

    public Boolean call() throws Exception {
        boolean isSuccess = false;
        NioEventLoopGroup group = new NioEventLoopGroup();
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(group).channel(NioSocketChannel.class);
            bootstrap.remoteAddress(new InetSocketAddress(this.host,this.port));
            ChannelInitializer<SocketChannel> channelInitializer = new ChannelInitializer<SocketChannel>() {
                public void initChannel(SocketChannel ch) throws Exception {
                    ch.pipeline()
                            .addLast(new ChannelHandler[]{new ObjectEncoder()})
                            .addLast(new ChannelHandler[]{new StringEncoder()})
                            .addLast(new ChannelHandler[]{new GraphiteNettyClientHandler()});
                }
            };
            bootstrap.handler(channelInitializer);
            ChannelFuture future = bootstrap.connect().sync();
            if (future.isSuccess()) {
                logger.info("连接：" + this.host + ":" + this.port + "，成功！");
                Channel channel = future.channel();
                StringBuffer data = new StringBuffer();
                Iterator metric = this.graphiteMetrics.iterator();

                while(metric.hasNext()) {
                    GraphiteMetric graphiteMetric = (GraphiteMetric)metric.next();
                    data.append(String.format("%s %s %s", graphiteMetric.getMetricName(), graphiteMetric.getValue(), graphiteMetric.getTime())).append("\n");
                    data.append(String.format("%s %s %s", graphiteMetric.getMetricName(), graphiteMetric.getValue(), graphiteMetric.getTime())).append("\n");
                }
                logger.info("性能数据：\n" + data.toString());
                channel.writeAndFlush(Unpooled.copiedBuffer(data.toString().getBytes())).addListener(ChannelFutureListener.CLOSE);
                logger.info("数据发送成功！");
                isSuccess = true;
            }
            future.channel().closeFuture().sync();
        } catch (Exception e) {
            logger.error("连接：{}:{} 错误：{}",this.host,this.port,e.getMessage());
        } finally {
            group.shutdownGracefully();
        }
        return isSuccess;
    }
}
